/************************************************************
 * Project Name		[Thinking_In_Java]
 * File Name     	[pkg_05_swing.Example_09_Mouse_Event.java]
 * Creation Date 	[22-Jun-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_05_swing;

import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JComponent;
import javax.swing.JFrame;

/**
 * 鼠标事件
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class Example_09_Mouse_Event {

	/**
	 * 测试方法
	 * 
	 * @param args
	 *            命令行参数
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				MouseFrame frame = new MouseFrame();
				frame.setVisible(true);
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setResizable(true);
			}
		});
	}
}

/**
 * Mouse frame
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 */
class MouseFrame extends JFrame {

	private static final long serialVersionUID = -1012994310801339804L;

	/**
	 * 构造方法
	 */
	public MouseFrame() {
		this.setTitle("Mouse Event");
		this.setSize(300, 200);
		this.setLocationByPlatform(true);

		MouseComponent component = new MouseComponent();
		this.add(component);// = this.getContentPane().add(component);
	}
}

/**
 * Mouse component
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 */
class MouseComponent extends JComponent {

	private static final long serialVersionUID = -107304944461598382L;

	private static final int SIDE_LENGTH = 10;

	private ArrayList<Rectangle2D> squares = null;

	// 当前矩形
	private Rectangle2D current = null;

	/**
	 * 构造方法
	 */
	public MouseComponent() {
		squares = new ArrayList<Rectangle2D>();
		current = null;

		this.addMouseListener(new MouseHandler());
		this.addMouseMotionListener(new MouseMotionHandler());
	}

	/**
	 * 绘制矩形
	 * 
	 * @param g
	 *            绘制的画笔
	 */
	@Override
	protected void paintComponent(Graphics g) {
		Graphics2D g2 = (Graphics2D) g;

		// 绘制每一个矩形
		for (Rectangle2D square : squares) {
			g2.draw(square);
		}
	}

	/**
	 * 查找矩形是否包含该点坐标
	 * 
	 * @param point
	 *            待检测的坐标点
	 * @return 如果包含坐标点则返回包含该点的矩形
	 */
	public Rectangle2D findRectangle(Point2D point) {
		for (Rectangle2D square : squares) {
			if (square.contains(point)) {
				return square;
			}
		}
		return null;
	}

	/**
	 * 根据点的坐标绘制矩形, 并重绘画布
	 * 
	 * @param point
	 *            绘制的坐标点
	 */
	public void addRectangle(Point2D point) {
		double x = point.getX();
		double y = point.getY();

		current = new Rectangle2D.Double(x - SIDE_LENGTH / 2, y - SIDE_LENGTH
				/ 2, SIDE_LENGTH, SIDE_LENGTH);
		squares.add(current);
		this.repaint();
	}

	/**
	 * 从屏幕上擦除矩形, 并重绘画布
	 * 
	 * @param rectangle
	 *            待擦除的矩形
	 */
	public void removeRectangle(Rectangle2D rectangle) {
		if (rectangle == null) {
			return;
		}
		if (rectangle == current) {
			current = null;
		}
		squares.remove(rectangle);
		this.repaint();
	}

	/**
	 * 鼠标监听器
	 * 
	 * @author 不落的太阳(Sean Yang)
	 * @version 1.0
	 * @since JDK 6
	 */
	private class MouseHandler extends MouseAdapter {

		@Override
		public void mousePressed(MouseEvent event) {
			// 如果光标不在任何矩形内, 添加一个新的矩形
			current = findRectangle(event.getPoint());
			if (current == null) {
				addRectangle(event.getPoint());
			}
		}

		@Override
		public void mouseClicked(MouseEvent event) {
			current = findRectangle(event.getPoint());
			// 如果光标在矩形内, 且点击次数超过2次, 则将此矩形从屏幕擦除
			if (current != null && event.getClickCount() >= 2) {
				removeRectangle(current);
			}
		}
	}

	/**
	 * 鼠标动作监听器
	 * 
	 * @author 不落的太阳(Sean Yang)
	 * @version 1.0
	 * @since JDK 6
	 */
	private class MouseMotionHandler implements MouseMotionListener {

		/**
		 * 矩形的位置随着鼠标的拖拽而改变
		 */
		public void mouseDragged(MouseEvent event) {
			// 为什么可以直接检测null, 因为拖拽之前首先是鼠标按下, 会调用上面的MouseHandler监听器
			if (current != null) {
				int x = event.getX();
				int y = event.getY();

				current.setFrame(x - SIDE_LENGTH / 2, y - SIDE_LENGTH / 2,
						SIDE_LENGTH, SIDE_LENGTH);
				repaint();
			}
		}

		/**
		 * 设置鼠标光标形态
		 */
		public void mouseMoved(MouseEvent event) {
			if (findRectangle(event.getPoint()) == null) {
				setCursor(Cursor.getDefaultCursor());
			} else {
				setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
			}
		}
	}
}
